/*
 * Copyright 2012-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.webservices.client;

import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.xml.transform.TransformerFactory;

import org.springframework.beans.BeanUtils;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.support.destination.DestinationProvider;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;

/**
 * 用于配置和创建 {@link WebServiceTemplate} 的构建器。提供方便的方法来注册
 * {@link #messageSenders(WebServiceMessageSender...) 消息发送器}、
 * {@link #interceptors(ClientInterceptor...) 客户端拦截器} 和
 * {@link #customizers(WebServiceTemplateCustomizer...) 自定义器}。
 * <p>
 * 默认情况下，构建的 {@link WebServiceTemplate} 使用最合适的基于 HTTP 的
 * {@link WebServiceMessageSender}，如果您希望保留默认行为，可以调用
 * {@link #detectHttpMessageSender(boolean) detectHttpMessageSender(false)}。
 * 在典型的自动配置 Spring Boot 应用中，此构建器作为一个 Bean 可用，
 * 并且可以在需要 {@link WebServiceTemplate} 时注入。
 *
 * @author Dmytro Nosan
 * @author Stephane Nicoll
 * @since 2.1.0
 */
public class WebServiceTemplateBuilder {

	private final boolean detectHttpMessageSender;

	private final Set<ClientInterceptor> interceptors;

	private final Set<WebServiceTemplateCustomizer> internalCustomizers;

	private final Set<WebServiceTemplateCustomizer> customizers;

	private final WebServiceMessageSenders messageSenders;

	private final Marshaller marshaller;

	private final Unmarshaller unmarshaller;

	private final DestinationProvider destinationProvider;

	private final Class<? extends TransformerFactory> transformerFactoryClass;

	private final WebServiceMessageFactory messageFactory;

	public WebServiceTemplateBuilder(WebServiceTemplateCustomizer... customizers) {
		this.detectHttpMessageSender = true;
		this.interceptors = null;
		this.internalCustomizers = null;
		this.customizers = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(customizers)));
		this.messageSenders = new WebServiceMessageSenders();
		this.marshaller = null;
		this.unmarshaller = null;
		this.destinationProvider = null;
		this.transformerFactoryClass = null;
		this.messageFactory = null;
	}

	private WebServiceTemplateBuilder(boolean detectHttpMessageSender, Set<ClientInterceptor> interceptors,
			Set<WebServiceTemplateCustomizer> internalCustomizers, Set<WebServiceTemplateCustomizer> customizers,
			WebServiceMessageSenders messageSenders, Marshaller marshaller, Unmarshaller unmarshaller,
			DestinationProvider destinationProvider, Class<? extends TransformerFactory> transformerFactoryClass,
			WebServiceMessageFactory messageFactory) {
		this.detectHttpMessageSender = detectHttpMessageSender;
		this.interceptors = interceptors;
		this.internalCustomizers = internalCustomizers;
		this.customizers = customizers;
		this.messageSenders = messageSenders;
		this.marshaller = marshaller;
		this.unmarshaller = unmarshaller;
		this.destinationProvider = destinationProvider;
		this.transformerFactoryClass = transformerFactoryClass;
		this.messageFactory = messageFactory;
	}

	/**
	 * 设置是否应该基于类路径检测合适的基于 HTTP 的 {@link WebServiceMessageSender}。默认值为 {@code true}。
	 * @param detectHttpMessageSender 是否检测基于 HTTP 的 {@link WebServiceMessageSender}
	 * @return 新的构建器实例
	 * @see HttpWebServiceMessageSenderBuilder
	 */
	public WebServiceTemplateBuilder detectHttpMessageSender(boolean detectHttpMessageSender) {
		return new WebServiceTemplateBuilder(detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置 {@link WebServiceTemplate} 应使用的 {@link WebServiceMessageSender}。设置此值将替换
	 * 之前定义的所有消息发送器（包括基于 HTTP 的消息发送器，如果有的话）。
	 * 建议使用 {@link #additionalMessageSenders(WebServiceMessageSender...)} 来保留用户自定义的消息发送器。
	 * @param messageSenders 要设置的消息发送器
	 * @return 新的构建器实例
	 * @see #additionalMessageSenders(WebServiceMessageSender...)
	 * @see #detectHttpMessageSender(boolean)
	 */
	public WebServiceTemplateBuilder messageSenders(WebServiceMessageSender... messageSenders) {
		Assert.notNull(messageSenders, "MessageSenders must not be null");
		return messageSenders(Arrays.asList(messageSenders));
	}

	/**
	 * 设置 {@link WebServiceTemplate} 应使用的 {@link WebServiceMessageSender}。设置此值将替换
	 * 之前定义的所有消息发送器（包括基于 HTTP 的消息发送器，如果有的话）。
	 * 建议使用 {@link #additionalMessageSenders(Collection)} 来保留用户自定义的消息发送器。
	 * @param messageSenders 要设置的消息发送器集合
	 * @return 新的构建器实例
	 * @see #additionalMessageSenders(Collection)
	 * @see #detectHttpMessageSender(boolean)
	 */
	public WebServiceTemplateBuilder messageSenders(Collection<? extends WebServiceMessageSender> messageSenders) {
		Assert.notNull(messageSenders, "MessageSenders must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders.set(messageSenders), this.marshaller, this.unmarshaller,
				this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 添加额外的 {@link WebServiceMessageSender}，这些发送器将用于 {@link WebServiceTemplate}。
	 * @param messageSenders 要添加的消息发送器
	 * @return 新的构建器实例
	 * @see #messageSenders(WebServiceMessageSender...)
	 */
	public WebServiceTemplateBuilder additionalMessageSenders(WebServiceMessageSender... messageSenders) {
		Assert.notNull(messageSenders, "MessageSenders must not be null");
		return additionalMessageSenders(Arrays.asList(messageSenders));
	}

	/**
	 * 添加额外的 {@link WebServiceMessageSender}，这些发送器将用于 {@link WebServiceTemplate}。
	 * @param messageSenders 要添加的消息发送器集合
	 * @return 新的构建器实例
	 * @see #messageSenders(Collection)
	 */
	public WebServiceTemplateBuilder additionalMessageSenders(
			Collection<? extends WebServiceMessageSender> messageSenders) {
		Assert.notNull(messageSenders, "MessageSenders must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders.add(messageSenders), this.marshaller, this.unmarshaller,
				this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置 {@link WebServiceTemplate} 应使用的 {@link ClientInterceptor}。设置此值将替换之前定义的所有拦截器。
	 * @param interceptors 要设置的拦截器
	 * @return 新的构建器实例
	 * @see #additionalInterceptors(ClientInterceptor...)
	 */
	public WebServiceTemplateBuilder interceptors(ClientInterceptor... interceptors) {
		Assert.notNull(interceptors, "Interceptors must not be null");
		return interceptors(Arrays.asList(interceptors));
	}

	/**
	 * 设置 {@link WebServiceTemplate} 应使用的 {@link ClientInterceptor}。设置此值将替换之前定义的所有拦截器。
	 * @param interceptors 要设置的拦截器集合
	 * @return 新的构建器实例
	 * @see #additionalInterceptors(Collection)
	 */
	public WebServiceTemplateBuilder interceptors(Collection<? extends ClientInterceptor> interceptors) {
		Assert.notNull(interceptors, "Interceptors must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender,
				append(Collections.<ClientInterceptor>emptySet(), interceptors), this.internalCustomizers,
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 添加额外的 {@link ClientInterceptor}，这些拦截器将用于 {@link WebServiceTemplate}。
	 * @param interceptors 要添加的拦截器
	 * @return 新的构建器实例
	 * @see #interceptors(ClientInterceptor...)
	 */
	public WebServiceTemplateBuilder additionalInterceptors(ClientInterceptor... interceptors) {
		Assert.notNull(interceptors, "Interceptors must not be null");
		return additionalInterceptors(Arrays.asList(interceptors));
	}

	/**
	 * 添加额外的 {@link ClientInterceptor}，这些拦截器将用于 {@link WebServiceTemplate}。
	 * @param interceptors 要添加的拦截器集合
	 * @return 新的构建器实例
	 * @see #interceptors(Collection)
	 */
	public WebServiceTemplateBuilder additionalInterceptors(Collection<? extends ClientInterceptor> interceptors) {
		Assert.notNull(interceptors, "Interceptors must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, append(this.interceptors, interceptors),
				this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller, this.unmarshaller,
				this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置应应用于 {@link WebServiceTemplate} 的 {@link WebServiceTemplateCustomizer}。自定义器将按添加顺序依次应用，
	 * 在构建器配置之后。设置此值将替换任何之前配置的自定义器。
	 * @param customizers 要设置的自定义器
	 * @return 新的构建器实例
	 * @see #additionalCustomizers(WebServiceTemplateCustomizer...)
	 */
	public WebServiceTemplateBuilder customizers(WebServiceTemplateCustomizer... customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		return customizers(Arrays.asList(customizers));
	}

	/**
	 * 设置应应用于 {@link WebServiceTemplate} 的 {@link WebServiceTemplateCustomizer}。自定义器会按添加顺序依次应用，
	 * 并且在构建器的其他配置应用之后。设置此值会替换之前配置的所有自定义器。
	 * @param customizers 要设置的自定义器集合
	 * @return 新的构建器实例
	 * @see #additionalCustomizers(Collection)
	 */
	public WebServiceTemplateBuilder customizers(Collection<? extends WebServiceTemplateCustomizer> customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				append(Collections.<WebServiceTemplateCustomizer>emptySet(), customizers), this.messageSenders,
				this.marshaller, this.unmarshaller, this.destinationProvider, this.transformerFactoryClass,
				this.messageFactory);
	}

	/**
	 * 添加额外的 {@link WebServiceTemplateCustomizer}，这些自定义器会被应用到 {@link WebServiceTemplate}。
	 * 自定义器会按添加顺序依次应用，并且在构建器的其他配置应用之后。
	 * @param customizers 要添加的自定义器
	 * @return 新的构建器实例
	 * @see #customizers(WebServiceTemplateCustomizer...)
	 */
	public WebServiceTemplateBuilder additionalCustomizers(WebServiceTemplateCustomizer... customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		return additionalCustomizers(Arrays.asList(customizers));
	}

	/**
	 * 添加额外的 {@link WebServiceTemplateCustomizer}，这些自定义器会被应用到 {@link WebServiceTemplate}。
	 * 自定义器会按添加顺序依次应用，并且在构建器的其他配置应用之后。
	 * @param customizers 要添加的自定义器集合
	 * @return 新的构建器实例
	 * @see #customizers(Collection)
	 */
	public WebServiceTemplateBuilder additionalCustomizers(
			Collection<? extends WebServiceTemplateCustomizer> customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				append(this.customizers, customizers), this.messageSenders, this.marshaller, this.unmarshaller,
				this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 指示是否应检查连接中的故障指示器（{@code true}），或者仅依赖消息本身（{@code false}）。
	 * @param checkConnectionForFault 是否检查连接中的故障指示器
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setCheckConnectionForFault(boolean)
	 */
	public WebServiceTemplateBuilder setCheckConnectionForFault(boolean checkConnectionForFault) {
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors,
				append(this.internalCustomizers, new CheckConnectionFaultCustomizer(checkConnectionForFault)),
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 指示是否应检查连接中的错误指示器（{@code true}），还是忽略这些错误指示器（{@code false}）。
	 * @param checkConnectionForError 是否检查连接中的错误指示器
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setCheckConnectionForError(boolean)
	 */
	public WebServiceTemplateBuilder setCheckConnectionForError(boolean checkConnectionForError) {
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors,
				append(this.internalCustomizers, new CheckConnectionForErrorCustomizer(checkConnectionForError)),
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置用于创建消息的 {@link WebServiceMessageFactory}。
	 * @param messageFactory 用于创建消息的消息工厂
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setMessageFactory(WebServiceMessageFactory)
	 */
	public WebServiceTemplateBuilder setWebServiceMessageFactory(WebServiceMessageFactory messageFactory) {
		Assert.notNull(messageFactory, "MessageFactory must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, messageFactory);
	}

	/**
	 * 设置用于反序列化消息的 {@link Unmarshaller}。
	 * @param unmarshaller 消息反序列化器
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setUnmarshaller(Unmarshaller)
	 */
	public WebServiceTemplateBuilder setUnmarshaller(Unmarshaller unmarshaller) {
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders, this.marshaller, unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置用于序列化消息的 {@link Marshaller}。
	 * @param marshaller 消息序列化器
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setMarshaller(Marshaller)
	 */
	public WebServiceTemplateBuilder setMarshaller(Marshaller marshaller) {
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders, marshaller, this.unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置要使用的 {@link FaultMessageResolver}。
	 * @param faultMessageResolver 要使用的故障消息解析器
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setFaultMessageResolver(FaultMessageResolver)
	 */
	public WebServiceTemplateBuilder setFaultMessageResolver(FaultMessageResolver faultMessageResolver) {
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors,
				append(this.internalCustomizers, new FaultMessageResolverCustomizer(faultMessageResolver)),
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置要使用的 {@link TransformerFactory} 实现类。
	 * @param transformerFactoryClass 要使用的转换器工厂实现类
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setTransformerFactoryClass(Class)
	 */
	public WebServiceTemplateBuilder setTransformerFactoryClass(
			Class<? extends TransformerFactory> transformerFactoryClass) {
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
				transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 设置默认的 URI，应用于没有 URI 参数的操作。
	 * 通常，该属性与 {@link #setDestinationProvider(DestinationProvider)} 互斥设置。
	 * @param defaultUri 用于没有 URI 参数的操作的默认目标 URI
	 * @return 新的构建器实例
	 * @see #setDestinationProvider(DestinationProvider)
	 */
	public WebServiceTemplateBuilder setDefaultUri(String defaultUri) {
		Assert.hasText(defaultUri, "DefaultUri must not be empty");
		return setDestinationProvider(() -> URI.create(defaultUri));
	}

	/**
	 * 设置要使用的 {@link DestinationProvider}。
	 * 通常，该属性与 {@link #setDefaultUri(String)} 互斥设置。
	 * @param destinationProvider 用于没有 URI 参数操作的目标提供者
	 * @return 新的构建器实例
	 * @see WebServiceTemplate#setDestinationProvider(DestinationProvider)
	 */
	public WebServiceTemplateBuilder setDestinationProvider(DestinationProvider destinationProvider) {
		Assert.notNull(destinationProvider, "DestinationProvider must not be null");
		return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
				this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, destinationProvider,
				this.transformerFactoryClass, this.messageFactory);
	}

	/**
	 * 构建一个新的 {@link WebServiceTemplate} 实例，并使用此构建器进行配置。
	 * @return 配置完成的 {@link WebServiceTemplate} 实例
	 * @see #build(Class)
	 * @see #configure(WebServiceTemplate)
	 */
	public WebServiceTemplate build() {
		return configure(new WebServiceTemplate());
	}

	/**
	 * 构建指定类型的 {@link WebServiceTemplate} 实例，并使用此构建器进行配置。
	 * @param <T> WebServiceTemplate 的类型
	 * @param webServiceTemplateClass 要创建的模板类型
	 * @return 配置完成的 {@link WebServiceTemplate} 实例
	 * @see WebServiceTemplateBuilder#build()
	 * @see #configure(WebServiceTemplate)
	 */
	public <T extends WebServiceTemplate> T build(Class<T> webServiceTemplateClass) {
		Assert.notNull(webServiceTemplateClass, "WebServiceTemplateClass must not be null");
		return configure(BeanUtils.instantiateClass(webServiceTemplateClass));
	}

	/**
	 * 使用此构建器配置提供的 {@link WebServiceTemplate} 实例。
	 * @param <T> WebServiceTemplate 的类型
	 * @param webServiceTemplate 要配置的 {@link WebServiceTemplate} 实例
	 * @return 配置完成的 WebServiceTemplate 实例
	 * @see #build()
	 * @see #build(Class)
	 */
	public <T extends WebServiceTemplate> T configure(T webServiceTemplate) {
		Assert.notNull(webServiceTemplate, "WebServiceTemplate must not be null");
		configureMessageSenders(webServiceTemplate);
		PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
		applyCustomizers(webServiceTemplate, this.internalCustomizers);
		map.from(this.marshaller).to(webServiceTemplate::setMarshaller);
		map.from(this.unmarshaller).to(webServiceTemplate::setUnmarshaller);
		map.from(this.destinationProvider).to(webServiceTemplate::setDestinationProvider);
		map.from(this.transformerFactoryClass).to(webServiceTemplate::setTransformerFactoryClass);
		map.from(this.messageFactory).to(webServiceTemplate::setMessageFactory);
		if (!CollectionUtils.isEmpty(this.interceptors)) {
			Set<ClientInterceptor> merged = new LinkedHashSet<>(this.interceptors);
			if (webServiceTemplate.getInterceptors() != null) {
				merged.addAll(Arrays.asList(webServiceTemplate.getInterceptors()));
			}
			webServiceTemplate.setInterceptors(merged.toArray(new ClientInterceptor[0]));
		}
		applyCustomizers(webServiceTemplate, this.customizers);
		return webServiceTemplate;
	}

	private void applyCustomizers(WebServiceTemplate webServiceTemplate,
			Set<WebServiceTemplateCustomizer> customizers) {
		if (!CollectionUtils.isEmpty(customizers)) {
			for (WebServiceTemplateCustomizer customizer : customizers) {
				customizer.customize(webServiceTemplate);
			}
		}
	}

	private <T extends WebServiceTemplate> void configureMessageSenders(T webServiceTemplate) {
		if (this.messageSenders.isOnlyAdditional() && this.detectHttpMessageSender) {
			Set<WebServiceMessageSender> merged = append(this.messageSenders.getMessageSenders(),
					new HttpWebServiceMessageSenderBuilder().build());
			webServiceTemplate.setMessageSenders(merged.toArray(new WebServiceMessageSender[0]));
		}
		else if (!CollectionUtils.isEmpty(this.messageSenders.getMessageSenders())) {
			webServiceTemplate
					.setMessageSenders(this.messageSenders.getMessageSenders().toArray(new WebServiceMessageSender[0]));
		}
	}

	private <T> Set<T> append(Set<T> set, T addition) {
		return append(set, Collections.singleton(addition));
	}

	private static <T> Set<T> append(Set<T> set, Collection<? extends T> additions) {
		Set<T> result = new LinkedHashSet<>((set != null) ? set : Collections.emptySet());
		result.addAll((additions != null) ? additions : Collections.emptyList());
		return Collections.unmodifiableSet(result);
	}

	/**
	 * 收集用户定义的 {@link WebServiceMessageSender} 以及是否仅添加了额外的消息发送器。
	 */
	private static final class WebServiceMessageSenders {

		private final boolean onlyAdditional;

		private Set<WebServiceMessageSender> messageSenders;

		private WebServiceMessageSenders() {
			this(true, Collections.emptySet());
		}

		private WebServiceMessageSenders(boolean onlyAdditional, Set<WebServiceMessageSender> messageSenders) {
			this.onlyAdditional = onlyAdditional;
			this.messageSenders = messageSenders;
		}

		boolean isOnlyAdditional() {
			return this.onlyAdditional;
		}

		Set<WebServiceMessageSender> getMessageSenders() {
			return this.messageSenders;
		}

		WebServiceMessageSenders set(Collection<? extends WebServiceMessageSender> messageSenders) {
			return new WebServiceMessageSenders(false, new LinkedHashSet<>(messageSenders));
		}

		WebServiceMessageSenders add(Collection<? extends WebServiceMessageSender> messageSenders) {
			return new WebServiceMessageSenders(this.onlyAdditional, append(this.messageSenders, messageSenders));
		}

	}

	/**
	 * 用于设置 {@link WebServiceTemplate#setCheckConnectionForFault(boolean) checkConnectionForFault} 的
	 * {@link WebServiceTemplateCustomizer} 实现类。
	 */
	private static final class CheckConnectionFaultCustomizer implements WebServiceTemplateCustomizer {

		private final boolean checkConnectionFault;

		private CheckConnectionFaultCustomizer(boolean checkConnectionFault) {
			this.checkConnectionFault = checkConnectionFault;
		}

		@Override
		public void customize(WebServiceTemplate webServiceTemplate) {
			webServiceTemplate.setCheckConnectionForFault(this.checkConnectionFault);
		}

	}

	/**
	 * 用于设置 {@link WebServiceTemplate#setCheckConnectionForError(boolean) checkConnectionForError} 的
	 * {@link WebServiceTemplateCustomizer} 实现类。
	 */
	private static final class CheckConnectionForErrorCustomizer implements WebServiceTemplateCustomizer {

		private final boolean checkConnectionForError;

		private CheckConnectionForErrorCustomizer(boolean checkConnectionForError) {
			this.checkConnectionForError = checkConnectionForError;
		}

		@Override
		public void customize(WebServiceTemplate webServiceTemplate) {
			webServiceTemplate.setCheckConnectionForError(this.checkConnectionForError);
		}

	}

	/**
	 * 用于设置 {@link WebServiceTemplate#setFaultMessageResolver(FaultMessageResolver) faultMessageResolver} 的
	 * {@link WebServiceTemplateCustomizer} 实现类。
	 */
	private static final class FaultMessageResolverCustomizer implements WebServiceTemplateCustomizer {

		private final FaultMessageResolver faultMessageResolver;

		private FaultMessageResolverCustomizer(FaultMessageResolver faultMessageResolver) {
			this.faultMessageResolver = faultMessageResolver;
		}

		@Override
		public void customize(WebServiceTemplate webServiceTemplate) {
			webServiceTemplate.setFaultMessageResolver(this.faultMessageResolver);
		}

	}

}
